package com.nandi.emergencyinspection.customconfig

import android.widget.Toast
import com.blankj.utilcode.util.ToastUtils
import com.google.gson.JsonSyntaxException
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import com.nandi.emergencyinspection.utils.SSLSocketClient
import com.tbright.ktbaselibrary.base.BaseResponse
import com.tbright.ktbaselibrary.event.MessageEvent
import com.tbright.ktbaselibrary.global.GlobalConfig
import com.tbright.ktbaselibrary.global.TIME_OUT
import com.tbright.ktbaselibrary.net.exception.NoNetworkException
import com.tbright.ktbaselibrary.net.interceptor.CacheInterceptor
import com.tbright.ktbaselibrary.net.interceptor.MultiUrlInterceptor
import com.tbright.ktbaselibrary.proxy.HttpConfigProxy
import kotlinx.coroutines.Deferred
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONException
import retrofit2.HttpException
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.InterruptedIOException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLHandshakeException


const val UNAUTHORIZED = 401
const val FORBIDDEN = 403
const val YZMBHF = 428
const val PASSWORD = 426
const val NOT_FOUND = 404
const val REQUEST_TIMEOUT = 408
const val INTERNAL_SERVER_ERROR = 500
const val BAD_GATEWAY = 502
const val SERVICE_UNAVAILABLE = 503
const val GATEWAY_TIMEOUT = 504

const val EVENTCODE_RELOGIN = 998 //需要重新登录
const val EVENTCODE_RESPONSE_FAIL = 999 //http请求失败

const val BASE_URL = "base_Url"

//const val mBaseUrl = " http://192.168.10.170:8080/lh/"
const val mBaseUrl = "http://lhgateway.cn1.utools.club/luohu_api/"
//const val mBaseUrl = "http://172.16.0.73:9999/"
//const val mBaseUrl = "https://139.159.189.117:443/luohu_api/"
//const val mBaseUrl = "https://139.159.189.117:832/luohu_api/"

const val IM_URL = "im_Url"

//const val mImUrl = " http://192.168.10.170:8080/lh/"
const val mImUrl = "http://lhgateway.cn1.utools.club/luohu_api/"
//const val mImUrl = "https://139.159.189.117:832/luohu_api/"
//const val mImUrl = "https://139.159.189.117:443/luohu_api/"

class HttpConfig : HttpConfigProxy() {

    private var mRetrofit: Retrofit? = null

    private var mRetrofitBuilder: Retrofit.Builder? = null

    private var mOkHttpClientBuilder: OkHttpClient.Builder? = null

    //
    override var baseUrl: String = mBaseUrl

    override var baseUrls: Map<String, String>
        set(value) {}
        get() {
            var urls = linkedMapOf<String, String>()
            if (urls.isNotEmpty()) return urls
            if (GlobalConfig.isDebug) {//可以在这里动态切换服务
                urls[BASE_URL] = mBaseUrl
                urls[IM_URL] = mImUrl
            } else {
                urls[BASE_URL] = mBaseUrl
                urls[IM_URL] = mImUrl
            }
            return urls
        }

    override suspend fun <T> parseResponseData(responseData: Deferred<BaseResponse<T>>): T? {
        var response: BaseResponse<T>? = null
        try {
            response = responseData.await()
            val responseSuccess = response.isResponseSuccess()
            if (responseSuccess) {
                return response.getResponseData()
            } else {
                MessageEvent(EVENTCODE_RESPONSE_FAIL, response.getResponseMessage()).send()
                return null
            }
        } catch (e: Throwable) {
            var errMsg = "网络异常"
            when (e) {
                is UnknownHostException -> errMsg = "连接失败"
                is ConnectException -> errMsg = "连接失败"
                is SocketTimeoutException -> errMsg = "连接超时"
                is InterruptedIOException -> errMsg = "连接中断"
                is SSLHandshakeException -> errMsg = "证书验证失败"
                is JSONException -> errMsg = "数据解析错误"
                is JsonSyntaxException -> errMsg = "数据解析错误"
                is NoNetworkException -> errMsg = "无可用网络"
                is HttpException -> {

                    when (e.code()) {
                        UNAUTHORIZED, FORBIDDEN -> {//这两个一般会要求重新登录
                            MessageEvent(EVENTCODE_RELOGIN, errMsg).send()
                            return null
                        }
                        YZMBHF -> {
                            errMsg = "验证码不合法"
                        }
                        PASSWORD -> {
                            errMsg = "账户密码错误"
                        }
                        else -> errMsg = response?.getResponseMessage().toString()
                    }
                }
                else -> errMsg = e.message.toString()
            }

            MessageEvent(EVENTCODE_RESPONSE_FAIL, errMsg).send()
        }
        return null
    }

    override suspend fun <T> parseResponseWrapperData(
        responseData: Deferred<BaseResponse<T>>,
        vararg needDisposeError: Any
    ): BaseResponse<T>? {
        try {
            var response = responseData.await()
            if (response.isResponseSuccess()) {
                return response
            } else {
                if (needDisposeError.contains(response.getResponseStatus())) {//如果包含，不统一处理，在相应的页面特殊处理
                    return response
                } else {
                    MessageEvent(EVENTCODE_RESPONSE_FAIL, response.getResponseMessage()).send()
                    return null
                }
            }
        } catch (e: Throwable) {
            var errMsg = "网络异常"
            when (e) {
                is UnknownHostException -> errMsg = "连接失败"
                is ConnectException -> errMsg = "连接失败"
                is SocketTimeoutException -> errMsg = "连接超时"
                is InterruptedIOException -> errMsg = "连接中断"
                is SSLHandshakeException -> errMsg = "证书验证失败"
                is JSONException -> errMsg = "数据解析错误"
                is JsonSyntaxException -> errMsg = "数据解析错误"
                is NoNetworkException -> errMsg = "无可用网络"
                is HttpException -> {
                    val code = e.code()
                    when (code) {
                        UNAUTHORIZED, FORBIDDEN -> {//这两个一般会要求重新登录
                            MessageEvent(EVENTCODE_RELOGIN, errMsg).send()
                            return null
                        }
                        YZMBHF -> {
                            ToastUtils.showLong("验证码不合法")
                            errMsg = "验证码不合法"
                        }
                        PASSWORD -> {
                            ToastUtils.showLong("账户密码错误")
                            errMsg = "账户密码错误"
                        }
                    }
                }
                else -> errMsg = e.message.toString()
            }
            MessageEvent(EVENTCODE_RESPONSE_FAIL, errMsg).send()
        }
        return null
    }


    override fun initRetrofit() {
        initClient()
        mRetrofitBuilder = Retrofit.Builder()
        mRetrofit = mRetrofitBuilder?.run {
            baseUrl(
                GlobalConfig.httpConfigProxy?.baseUrl
                    ?: GlobalConfig.httpConfigProxy?.baseUrls!!.values.first()
            )//如果项目就一个域名，可以直接使用baseUrl，baseUrls可以不用管
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .client(mOkHttpClientBuilder!!.build())
                .build()
            build()
        }
    }

    private var mRetrofitServices = hashMapOf<String, Any>()

    @Suppress("UNCHECKED_CAST")
    override fun <T> create(clazz: Class<T>): T {
        var key = clazz.canonicalName
        var mRetrofitService = mRetrofitServices[key]
        if (mRetrofitService == null) {
            mRetrofitService = mRetrofit!!.create(clazz)
            mRetrofitServices[key!!] = mRetrofitService!!
        }
        return mRetrofitService as T
    }

    private fun initClient() {
        mOkHttpClientBuilder = OkHttpClient.Builder()

        mOkHttpClientBuilder?.run {
            val loggingInterceptor = HttpLoggingInterceptor()
            loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
            //设置 Debug Log 模式
            addInterceptor(loggingInterceptor)

            connectTimeout(TIME_OUT, TimeUnit.SECONDS)
            readTimeout(TIME_OUT, TimeUnit.SECONDS)
            writeTimeout(TIME_OUT, TimeUnit.SECONDS)

            //错误重连
            retryOnConnectionFailure(true)
            addInterceptor(CacheInterceptor())
            addInterceptor(HeaderInterceptor())
            addInterceptor(MultiUrlInterceptor())
            sslSocketFactory(SSLSocketClient.getSSLSocketFactory());
            hostnameVerifier(SSLSocketClient.getHostnameVerifier());
        }
    }

    private fun getFirstCn(cert: X509Certificate): String? {
        val subjectPrincipal = cert.subjectX500Principal.toString()
        for (token in subjectPrincipal.split(",".toRegex()).toTypedArray()) {
            val x = token.indexOf("CN=")
            if (x >= 0) {
                return token.substring(x + 3)
            }
        }
        return null
    }
}